from flask import abort
from flask import current_app
from flask import g, jsonify
from flask import render_template
from flask import request
from flask import session

from info import constants
from info import db
from info.models import News, User, Comment, CommentLike
from info.modules.news import news_blu
from info.response_code import RET
from info.utils.common import login_user_data


@news_blu.route('/<int:news_id>')
@login_user_data
def detail(news_id):
    ##################################以下是用户信息#################################################
    # user_id = session.get('user_id')
    #
    # user = None
    # if user_id:
    #     # 有值 说明用户登录了 登录之后查询信息
    #     try:
    #         user = User.query.get(user_id)
    #     except Exception as e:
    #         current_app.logger.error(e)

    user = g.user
    #######################一下是根据新闻id获取新闻详情############################################

    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        abort(404)
        # return jsonify(errno=RET.NODATA ,errmsg='没有此新闻')
    # 有可能返回为空
    if news is None:
        abort(404)
        # return jsonify(errno=RET.NODATA ,errmsg='没有此新闻')





    ########################以下是用户信息####################################
    # 根据点击排行获取指定条数的信息
    try:
        click_list = News.query.order_by(News.clicks.desc()).limit(constants.CLICK_RANK_MAX_NEWS)
    except Exception as e:
        current_app.logger.error(e)

    # 将对象列表转换为字典列表
    click_news = []
    for item in click_list:
        click_news.append(item.to_dict())

    ########################以下是判断用户是否收藏####################################
    is_collected = False  # 显示收藏
    is_followed = False   # 都没关注
    if user:
        if news in user.collection_news:
            is_collected = True

    #######################判断用户关注#######################################
        try:
            news_user = User.query.get(news.user_id)
        except Exception as e:
            return jsonify(errno=RET.DBERR ,errmsg='查询失败')
        #　news_user是发布新闻的作者
       #  user是登录的用户
        if news_user in user.followers:
            is_followed = True
    ########################以下是当前新闻的所有评论####################################
    try:
        comments = Comment.query.filter(Comment.news_id==news_id).order_by(Comment.create_time.desc()).all()
    except Exception as e:
        current_app.logger.error(e)
    if user:
        # 再这里查询Comment_Like中当前登录的用户的id信息
        try:
            comment_like_list = CommentLike.query.filter(CommentLike.user_id==user.id).all()
        except Exception as e:
            current_app.logger.error(e)
            # 将对象转换为对象列表
        user_comment_like_ids=[]
        for cl in comment_like_list:
            user_comment_like_ids.append(cl.comment_id)


    comments_list=[]
    for item in comments:
        comment_dict = item.to_dict()

        # 我们需要自己去判断当前用户是否对这个评论点赞
        comment_dict['is_like'] = False

        if user and item.id in user_comment_like_ids:
            comment_dict['is_like'] = True
        comments_list.append(comment_dict)



    data = {
        'user_info': user.to_dict() if user else None,
            'click_news':click_news,
            'news':news.to_dict(),
            'is_collected':is_collected,
            'is_followed':is_followed,
            'comments':comments_list
    }

    return render_template('news/detail.html',data=data)

    # return '%s'%news_id


"""
点击收藏的需求：因为收藏和取消收藏 传递数据是一样的  只不过是行为不同
所以我们定义一个参数action  值是2个  一个是收藏  一个是取消收藏

1.收藏必须是用户登录
2.接受前端提交的数据
3.数据效验
    3.1 news_id
    3.2 action
4.根据用户的行为进行业务逻辑的实现
5.更新数据
6.返回相应
"""


@news_blu.route('/news_collect',methods=['POST'])
@login_user_data
def news_collect():

# 1.收藏必须是用户登录
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg='用户未登录')
# 2.接受前端提交的数据
    news_id = request.json.get('news_id')
    action = request.json.get('action')
# 3.数据效验
#     3.1 news_id  判断此条新闻必需有(查询数据库)
    if news_id is None:
        return jsonify(errno=RET.PARAMERR,errmsg='参数错误')
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询失败')
    if not news:
        return jsonify(errno=RET.NODATA, errmsg='没有此条数据')

#     3.2 action
    if action not in ('cancel_collect','collect'):
        return jsonify(errno=RET.PARAMERR ,errmsg='参数错误')
# 4.根据用户的行为进行业务逻辑的实现
    if action == 'collect':
        # 收藏
        # 收藏过了就不能在收藏；先根据新闻id查询一下，如果有就说明收藏过了，如果没有就说明没有收藏
        if news not in user.collection_news:
            user.collection_news.append(news)
    else:
        # 取消收藏
        if news in user.collection_news:
            user.collection_news.remove(news)
# 5.更新数据
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
# 6.返回相应
    return jsonify(errno=RET.OK,errmsg='操作成功')

"""
评论的需求  1.必须是登录用户  要传递新闻的id评论内容
1.这个视图必须是登录用户才可以访问
2.要接受参数 news_id  content
3.俩个参数都必需有
4.判断news必须存在
5.数据入库
6.返回响应 同时新增的数据传递给前端
"""
@news_blu.route('/news_comment',methods=['POST'])
@login_user_data
def news_comment():
# 1.这个视图必须是登录用户才可以访问
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR ,errmsg='未登录')
# 2.要接受参数 new_id  content
    news_id = request.json.get('news_id')
    content = request.json.get('comment')
    parent_comment_id = request.json.get('parent_id')
# 3.俩个参数都必需有
    if not all([news_id,content]):
        return jsonify(errno=RET.PARAMERR ,errmsg='参数不全')
# 4.判断news必须存在
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR ,errmsg='查询失败')
    if not news:
        return jsonify(errno=RET.NODATA ,errmsg='未查询到此新闻')

# 5.数据入库
    comment = Comment()
    comment.user_id = user.id
    comment.news_id = news.id
    comment.content = content

    # 根据用户传递过来的评论的父id来判断用户是否跟帖                   回复
    if parent_comment_id:
        comment.parent_id = parent_comment_id

    try:
        db.session.add(comment)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
# 6.返回响应 同时新增的数据传递给前端
    return jsonify(errno=RET.OK ,errmsg='ok',data={'comment':comment.to_dict()})


"""
回复评论的参数有：新闻new_id   comment_id评论的id   回复的内容content  回复的人

"""



"""
点赞的需求：
    需要将用户信息，评论的id  点赞的状态传递给后端
1.点赞功能必须要登录
2. 接受参数，并且对参数进行判断
3.comment_id进行查询，并且判断 必须有评论
4.数据入库
5.返回响应

"""

@news_blu.route('/comment_like',methods=['POST'])
@login_user_data
def comment_like():
# 1.点赞功能必须要登录
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR ,errmsg='暂未登录')
# 2. 接受参数，并且对参数进行判断
    comment_id = request.json.get('comment_id')
    action = request.json.get('action')

    if not all([comment_id,action]):
        return jsonify(errno=RET.PARAMERR ,errmsg='参数不全')
    if action not in ['add','remove']:
        return jsonify(errno=RET.PARAMERR ,errmsg='action问题')

# 3.comment_id进行查询，并且判断 必须有评论
    try:
        comment = Comment.query.get(comment_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR ,errmsg='未查询此评论')
    if not comment:
        return jsonify(errno=RET.NODATA ,errmsg='没有此评论')
# 4.数据入库
    if action == 'add':
        # 点赞
        # 先查询用户是否点过赞
        comment_like = CommentLike.query.filter(CommentLike.comment_id==comment_id,
                                                CommentLike.user_id==user.id).first()
        if not comment_like:
            # 添加点赞
            cl = CommentLike()
            cl.comment_id = comment_id
            cl.user_id = user.id
            # 更新点赞
            comment.like_count += 1
            try:
                db.session.add(cl)
                db.session.commit()
            except Exception as e:
                db.session.rollback()
    else:
        # 取消点赞
        # 先查寻有没有点赞
        comment_like = CommentLike.query.filter(CommentLike.comment_id == comment_id,
                                                CommentLike.user_id == user.id).first()
        if comment_like:
            # 只有点赞之后才可以取消 吧点赞数量减一
            comment.like_count -= 1
            try:
                db.session.delete(comment_like)
                db.session.commit()
            except Exception as e:
                current_app.logger.error(e)
                db.session.rollback()
# 5.返回响应
    return jsonify(errno=RET.OK ,errmsg='ok')


"""
关注与取消关注
    # 1. 接收前端提交的数据 user_id action
    # 2. 这2个数据 必须都有
    # 3. action 必须是 'follow', 'unfollow'
    # 4. 根据业务逻辑完成功能
    # 5. 返回相应
"""
@news_blu.route('/followed_user',methods = ['POST'])
@login_user_data
def user_follow():
    user = g.user
    # 1. 接收前端提交的数据 user_id action
    user_id = request.json.get('user_id')
    action = request.json.get('action')
    # 2. 这2个数据 必须都有
    if not all([user_id,action]):
        return jsonify(errno=RET.PARAMERR,errmsg='参数不全')
    # 3. action 必须是 'follow', 'unfollow'
    if action not in ['follow','unfollow']:
        return jsonify(errno=RET.PARAMERR ,errmsg='参数不全')
        # 查询关注的user
    try:
        news_user = User.query.get(user_id)
    except Exception as e:
        return jsonify(errno=RET.DBERR,errmsg='数据查询失败')
    # 4. 根据业务逻辑完成功能
    if action == 'follow':
        # 关注
        if news_user not in user.followers:
            user.followers.append(news_user)
    else:
        # 取消关注
        if news_user in user.followers:
            user.followers.remove(news_user)

    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()


    # 5. 返回相应
    return jsonify(errno=RET.OK,errmsg='ok')
